package com.ywb.Service;

import com.ywb.mapper.TradeRecordMapper;
import com.ywb.pojo.TradeRecord;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

@Service
@RequiredArgsConstructor
public class TradeDataGenerator {

    private final TradeRecordMapper tradeRecordMapper;
    private final ThreadLocalRandom random = ThreadLocalRandom.current();

//     权重选择算法（采用二分法优化）
//    private Integer selectWeightedId(Map<Integer, Double> weightMap, int minId, int maxId) {
//        List<Integer> allIds = new ArrayList<>();
//        List<Double> weights = new ArrayList<>();
//        double totalWeight = 0;
//
//        // 构建权重列表
//        for (int id = minId; id <= maxId; id++) {
//            if (weightMap.containsKey(id)) {
//                double w = weightMap.get(id);
//                allIds.add(id);
//                weights.add(w);
//                totalWeight += w;
//            }
//        }
//
//        // 生成随机数并二分查找
//        double r = random.nextDouble() * totalWeight;
//        int left = 0, right = weights.size() - 1;
//        while (left < right) {
//            int mid = (left + right) / 2;
//            if (weights.subList(0, mid + 1).stream().mapToDouble(Double::doubleValue).sum() <= r) {
//                left = mid + 1;
//            } else {
//                right = mid;
//            }
//        }
//        return allIds.get(left);
//    }
    private Integer selectWeightedId(Map<Integer, Double> individualWeights,
                                     Map<Integer, Double> groupWeights,
                                     int minId, int maxId,
                                     int groupSize) {
        List<Integer> allIds = new ArrayList<>();
        List<Double> weights = new ArrayList<>();
        double totalWeight = 0;

        for (int id = minId; id <= maxId; id++) {
            double weight = 0;

            // 1. 优先检查单独设置的权重
            if (individualWeights.containsKey(id)) {
                weight = individualWeights.get(id);
            }
            // 2. 否则检查分组权重
            else {
                // 修改点：调整分组起始ID计算逻辑（ID从1开始）
                int groupStart = ((id - 1) / groupSize) * groupSize + 1;
                if (groupWeights.containsKey(groupStart)) {
                    weight = groupWeights.get(groupStart) / groupSize;
                }
            }

            // 3. 仅处理有效权重
            if (weight > 0) {
                allIds.add(id);
                weights.add(weight);
                totalWeight += weight;
            }
        }

        if (totalWeight == 0) return null;

        double r = random.nextDouble() * totalWeight;
        int left = 0, right = weights.size() - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (weights.subList(0, mid + 1).stream().mapToDouble(Double::doubleValue).sum() <= r) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return allIds.get(left);
    }
    // 数据生成核心方法
//    public void generateData(long totalRecords,
//                             Map<Integer, Double> countryWeights,
//                             Map<Integer, Double> commodityWeights) {
//        final int BATCH_SIZE = 5000;  // 每批插入数量
//        long startTime = System.currentTimeMillis();
//
//        // 日期范围参数
//        LocalDate startDate = LocalDate.of(2022, 1, 1);
//        LocalDate endDate = LocalDate.of(2024, 12, 31);
//        long dateRange = ChronoUnit.DAYS.between(startDate, endDate);
//
//        for (long i = 0; i < totalRecords; i += BATCH_SIZE) {
//            List<TradeRecord> batch = new ArrayList<>(BATCH_SIZE);
//
//            for (int j = 0; j < BATCH_SIZE && i + j < totalRecords; j++) {
//                // 生成各个字段
//                int commodityId = selectWeightedId(
//                        commodityWeights, 0, 450);
//                int countryId = selectWeightedId(
//                        countryWeights, 0, 50);
//
//
//
//                batch.add(new TradeRecord(
//                        null,
//                        commodityId,
//                        countryId,
//                        random.nextBoolean() ? "进口" : "出口",
//                        new BigDecimal(String.format("%.2f", random.nextDouble() * 100000)),
//                        new BigDecimal(generateTariffRate()),
//                        startDate.plusDays(random.nextLong(dateRange + 1)),
//                        new Timestamp(System.currentTimeMillis()),
//                        new Timestamp(System.currentTimeMillis())
//                )
//
//                );
//            }
//
//            // 批量插入
//            tradeRecordMapper.batchInsert(batch);
//
//            // 性能监控
//            if (i % 100000 == 0) {
//                long elapsed = System.currentTimeMillis() - startTime;
//                if (i > 0) {
//                    // 计算每条记录的平均耗时（毫秒）
//                    double avgTimePerRecord = (double) elapsed / i;
//                    // 剩余记录数
//                    long remainingRecords = totalRecords - i;
//                    // 剩余时间估算（毫秒）
//                    long remainingMs = (long) (remainingRecords * avgTimePerRecord);
//                    // 转换为分钟
//                    long remainingMinutes = remainingMs / (60 * 1000);
//
//                    System.out.printf("已插入 %d 条，耗时 %d 秒，剩余预计 %d 分钟%n",
//                            i,
//                            elapsed / 1000,
//                            remainingMinutes);
//                } else {
//                    System.out.printf("已插入 %d 条，耗时 %d 秒，剩余时间未知%n", i, elapsed / 1000);
//                }
//            }
//        }
//    }
    public void generateData(long totalRecords,
                             Map<Integer, Double> countryWeights,
                             Map<Integer, Double> commodityWeights,
                             Map<Integer, Double> commodityGroupWeights,
                             int commodityGroupSize) {
        final int BATCH_SIZE = 5000;
        long startTime = System.currentTimeMillis();

        // 日期范围参数
        LocalDate startDate = LocalDate.of(2022, 1, 1);
        LocalDate endDate = LocalDate.of(2024, 12, 31);
        long dateRange = ChronoUnit.DAYS.between(startDate, endDate);

        for (long i = 0; i < totalRecords; i += BATCH_SIZE) {
            List<TradeRecord> batch = new ArrayList<>(BATCH_SIZE);

            for (int j = 0; j < BATCH_SIZE && i + j < totalRecords; j++) {
                // 生成各个字段
                int commodityId = selectWeightedId(
                        commodityWeights,
                        commodityGroupWeights,
                        1, 450,  // ID范围1-450
                        commodityGroupSize);

                int countryId = selectWeightedId(
                        countryWeights,  // 示例：country使用独立权重
                        new HashMap<>(),  // 示例：country未使用分组
                        1, 50, 10);      // 示例：country ID范围1-50，组大小10

                batch.add(new TradeRecord(
                        null,
                        commodityId,
                        countryId,
                        random.nextBoolean() ? "进口" : "出口",
                        new BigDecimal(String.format("%.2f", random.nextDouble() * 100000)),
                        new BigDecimal(generateTariffRate()),
                        startDate.plusDays(random.nextLong(dateRange + 1)),
                        new Timestamp(System.currentTimeMillis()),
                        new Timestamp(System.currentTimeMillis())
                ));
            }

            // 批量插入
            tradeRecordMapper.batchInsert(batch);

            // 性能监控
            if (i % 100000 == 0) {
                long elapsed = System.currentTimeMillis() - startTime;
                if (i > 0) {
                    double avgTimePerRecord = (double) elapsed / i;
                    long remainingRecords = totalRecords - i;
                    long remainingMs = (long) (remainingRecords * avgTimePerRecord);
                    long remainingMinutes = remainingMs / (60 * 1000);

                    System.out.printf("已插入 %d 条，耗时 %d 秒，剩余预计 %d 分钟%n",
                            i,
                            elapsed / 1000,
                            remainingMinutes);
                } else {
                    System.out.printf("已插入 %d 条，耗时 %d 秒，剩余时间未知%n", i, elapsed / 1000);
                }
            }
        }
    }
    private String generateTariffRate() {
        final double MEAN = 0.15;
        final double STD_DEV = 0.05;

        double rate;
        do {
            rate = random.nextGaussian() * STD_DEV + MEAN;
            rate = Math.max(0, Math.min(0.5, rate));
        } while (rate < 0 || rate > 0.5);

        return String.format("%.3f", rate).replace(',', '.');
    }
}
